#include "timerque.h"
#include "tinyrpc/base/task.h"
#include "tinyrpc/base/timestamp.h"
#include "eventloop.h"
namespace TinyRPC {

TimerQueue::TimerQueue(){
}

// 在eventloop里面注册读事件
void TimerQueue::timerQueueUpdateEvent(EventLoop* loop){
    m_timerChannel.setEventLoop(loop);
    m_timerChannel.updateEvent(ReadEvent, Task(std::bind(&TimerQueue::timerQueueTask, this), false), loop);
}

std::vector<Timer> TimerQueue::getAllExpired(){
    std::vector<Timer> expiredTimers;
    Timer timerNow = Timer(TimeStamp::Now(), TimeStamp(0), Task::EmptyTask());
    auto it = std::lower_bound(m_timers.begin(), m_timers.end(), timerNow);

    std::copy(m_timers.begin(), it, back_inserter(expiredTimers));
    m_timers.erase(m_timers.begin(), it);
    return expiredTimers;
}

EventPtr TimerQueue::getEventPtr(){
    return m_timerChannel.getEventPtr();
}


void TimerQueue::timerQueueTask(){
    m_timerChannel.read();

    std::vector<Timer> expiredTimers =  getAllExpired();
    
    for(Timer& timer : expiredTimers){
        timer.runTask();
        // 如果是周期的定时器, 还需要继续加入队列
        if(timer.isPeriod()){
            timer.nextPeriod();
            m_timers.insert(timer);
            //addTimer(timer);
        }
    }

    if(m_timers.empty()){
        m_latestTime = 0;
    }else{
        m_latestTime = m_timers.begin()->getStartTime();
        m_latestTime = TimeStamp::Now() > m_latestTime ? TimeStamp::Now() : m_latestTime;
        m_timerChannel.setTime(m_latestTime);
    }
}

void TimerQueue::addTimer(const Timer& timer){
    // 当插入的任务比较新的时候， 则需要从新设置一下m_timerChannel的事件
    if(timer.getStartTime() < m_latestTime || m_latestTime == 0){
        m_latestTime = timer.getStartTime();
        m_timers.insert(timer);
        m_timerChannel.setTime(m_latestTime);
    }else{
        m_timers.insert(timer);
    }
    
}
}
